#ifndef PAM_SRP_H
#define PAM_SRP_H

#include <stdarg.h>
#include <stdexcept>
#include <string>

namespace pam_srp
{

    class SRPException : public std::exception
    {
        std::string message;
        
      protected:
        void set_va_message( const char * fmt, va_list args );

      public:
        SRPException();
        
        SRPException( const char * fmt, ... );
        
        ~SRPException() throw() {}

        virtual const char * what() const throw() { return message.c_str(); }
    };

    
    class AuthenticationFailed : public SRPException
    {
      public:
        AuthenticationFailed( const char * fmt, ... );
    };

    
    class SRPError : public SRPException
    {
      public:
        int return_code; // defaults to PAM_SERVICE_ERR
        int syslog_code; // defaults to LOG_ERR
        
        SRPError( const char * fmt, ... );

        SRPError( const std::string & msg );
    };

    class NetworkError : public SRPException
    {
      public:
       NetworkError( const char * err_msg ) : SRPException(err_msg) {}
    };
    
    //--------------------------------------------------------------------------
    // pam_srp_settings.cpp
    //
    struct SRPSettings
    {
        std::string server;
        int         port;
        std::string public_key_file;
        std::string cred_cache_file;
        int         max_cached_creds;
        int         hash_alg;
        int         ng_type;

        void parse_file( const std::string & file_name, const std::string & cfg_name = "");
    };

    
    //--------------------------------------------------------------------------
    // pam_srp_net.cpp
    //
    bool test_connection( SRPSettings & settings );
    
    // new_password should be NULL unless we're changing the user's password
    //
    // throws: NetworkError if the connection fails or dies prematurely
    //
    void authenticate_from_network( SRPSettings & settings,
                                    const char * username, const char * password,
                                    bool & is_password_expired,
                                    const char * change_pass_username = 0, 
                                    const char * change_pass_password = 0,
                                    bool update_only_if_expired = false);

    
    //--------------------------------------------------------------------------
    // pam_srp_cache.cpp
    //
    void authenticate_from_cache( SRPSettings & settings,
                                  const char * username,
                                  const char * password );


    // Note: this must be called only after a successful network authentication
    void cache_credentials( SRPSettings & settings,
                            const char * username,
                            const char * password,
                            const char **cache_error );
    
} // end namespace pam_srp

#endif
